/*项目性能测试代码*/
#include "../logsys/log.hpp"
#include <chrono>
#include <vector>
#include <thread>

void Bench(const std::string& logger_name, size_t th_count, size_t msg_count, size_t msg_len)
{
    XKL::Logger::ptr logger = XKL::GetLogger(logger_name);
    if(logger.get() == nullptr)
        return ;
    std::cout << "测试日志：" << msg_count << "条, 总大小：" << (msg_count * msg_len) / 1024 << "KB" << std::endl;
    std::string msg(msg_len, 'A');
    std::vector<std::thread> threads;
    std::vector<double> costs(th_count);
    size_t msg_count_div = msg_count / th_count; // 将日志总量分配给每一个线程
    for(int i = 0; i < th_count; i++)
    {
        threads.emplace_back([&, i]()
        {
            auto start = std::chrono::high_resolution_clock::now();
            for(int j = 0; j < msg_count_div; j++)
                logger->fatal("%s", msg.c_str());
            auto end = std::chrono::high_resolution_clock::now();
            auto cost = std::chrono::duration_cast<std::chrono::duration<double>>(end-start);
            costs[i] = cost.count();
            std::cout << "\t线程" << i << ": " << "\t输出数量:" << msg_count_div << ", 耗时:" << cost.count() << "/s" << std::endl; 
        });
    }

    for(int i = 0; i < th_count; i++)
        threads[i].join();
    // 计算总耗时：在多并发场景下，最大耗时即为总耗时
    double max_cost = 0;
    for(auto cost: costs)
        max_cost = cost > max_cost ? cost: max_cost;
    
    size_t msg_div_sec = msg_count / max_cost;
    size_t size_div_sec = (msg_count * msg_len) / (max_cost * 1024); // 单位KB 
    std::cout << "\t总耗时: " << max_cost  << "/s" << std::endl;
    std::cout << "\t每秒输出量: " << msg_div_sec << "条" << std::endl;
    std::cout << "\t每秒输出大小: " << size_div_sec << "KB" << std::endl;
}

void sync()
{
    std::unique_ptr<XKL::LoggerBuilder> builder(new XKL::GlobalLoggerBuilder());
    builder->BuildLoggerLevel(XKL::LogLevel::DEBUG);
    builder->BuildLoggerName("sync-logger");
    builder->BuildLoggerType(XKL::LoggerType::LOGGER_SYNC);
    builder->BuildFormater("%m%n");
    builder->BuildSink<XKL::FileSink>("./logfile/test.log");
    builder->Build();

    Bench("sync-logger", 5, 1000000, 100);
}

void async()
{
    std::unique_ptr<XKL::LoggerBuilder> builder(new XKL::GlobalLoggerBuilder());
    builder->BuildLoggerLevel(XKL::LogLevel::DEBUG);
    builder->BuildLoggerName("async-logger");
    builder->EnableUnsafeAsync();
    builder->BuildLoggerType(XKL::LoggerType::LOGGER_ASYNC);
    builder->BuildFormater("%m%n");
    builder->BuildSink<XKL::FileSink>("./logfile/test.log");
    builder->Build();

    Bench("async-logger", 1, 1000000, 100);
}

int main()
{
    async();
    return 0;
}